#ifndef NRPSTG_GUIWIDGET_H
#define	NRPSTG_GUIWIDGET_H

#include <gl/gl.h>
#include <SDL.h>
#include <string>

using namespace std;

/**
 * These defines are for the purpose of the GuiRect struct, describing the index
 * in the value array wher each coordinate is. The coordinates are in real pixel
 * space.
 * X,Y are origin coords, W,H are width, height, L,T,R,B are left top right bottom
 */
#define GUI_X 0
#define GUI_Y 1
#define GUI_W 2
#define GUI_H 3
#define GUI_L 0
#define GUI_T 1
#define GUI_R 4
#define GUI_B 5

class GameData;
class GuiContainer;
class FontManager;

/**
 * Alignment enum. For horizontally aligned widgets.
 */
enum GUI_ALIGN {
    GUI_ALIGN_LEFT = 0,
    GUI_ALIGN_CENTER = 1,
    GUI_ALIGN_RIGHT = 2
};

/**
 * Alignment enum. For vertically aligned widgets.
 */
enum GUI_VALIGN {
    GUI_VALIGN_TOP = 0,
    GUI_VALIGN_CENTER = 1,
    GUI_VALIGN_BOTTOM = 2
};

/**
 * A struct for holding common properties of a widget (excluding position data)
 * Can be thought of as CSS properties kinda
 */
struct GuiProp {

    GUI_ALIGN align;
    GUI_VALIGN valign;
    /**
     * zindex is for rendering and event capturing. The higher the zindex, the
     * closer to the screen.
     */
    float zindex;

    /**
     * padding is the space between the borders of the bg and the actual displayed
     * element. Only absolute padding allowed.
     */
    int padding[4];
    /**
     * color affects any elements in the widget, such as text. Also becomes the
     * 'white' color in a texture. Elements are floats from 0.0f to 1.0f
     */
    float color[4];
    /**
     * Color of the background part of a widget. Same format as color.
     */
    float bg_color[4];

    GuiProp();
};

/**
 * A unified dimension class, containing a float percentage dimension and an
 * integer absolute dimension. The two are aggregated to produce a real screen
 * coordinate.
 */
struct GuiDim {
    /**
     * Represents a percentage of the parent widget's size, from 0.0f to 1.0f
     */
    float p;
    /**
     * Represents an absolute screen coordinate
     */
    int a;

    GuiDim();
    GuiDim(float pc, int abs);
};

/**
 * A GuiRect takes unified coordinates and calculates the real screen coordinates
 * based on the parent widget. It has 4 GuiDims for x,y,width, height, and stores
 * 6 values x,y,width,height,right,bottom. These values are not relative to the
 * parent widget, but are actual coordinates relative to 0,0 of the screen
 */
class GuiRect {
private:
    GuiDim _x;
    GuiDim _y;
    GuiDim _w;
    GuiDim _h;

    /**
     *[x,y,width,height,right,top]
     */
    int _val[6];

public:
    /**
     * Default constructor. All values are 0
     */
    GuiRect();
    /**
     * Creates a GuiRect based on an array of percents and absolutes
     * @param p a 4 element array of floats [x,y,width,height]
     * @param a a 4 element array of ints [x,y,width,height]
     */
    GuiRect(float* p, int* a);
    /**
     * Creates a GuiRect based on percentage
     * @param xp x percentage
     * @param yp y percentage
     * @param wp w percentage
     * @param hp h percentage
     */
    GuiRect(float xp, float yp, float wp, float hp);
    /**
     * Creates a GuiRect based on absolutes
     * @param xa
     * @param ya
     * @param wa
     * @param ha
     */
    GuiRect(int xa, int ya, int wa, int ha);
    /**
     * Creates a GuiRect based on absolutes and percentages
     * @param xp
     * @param xa
     * @param yp
     * @param ya
     * @param wp
     * @param wa
     * @param hp
     * @param ha
     */
    GuiRect(float xp, int xa, float yp, int ya, float wp, int wa, float hp, int ha);

    ~GuiRect();
    /**
     * The value is the calculated position and size for the rect
     * @return a 6-value int array [x,y,width,height,right,top]
     */
    int* value();

    /**
     * validates the values for the rect based on the values given. These
     * represent the values of the parent widget so that this position is
     * calculated relative to the full screen
     * @param x The x position of the parent
     * @param y The y position of the parent
     * @param w The width of the parent
     * @param h The height of the parent
     */
    void validate(int x=0, int y=0, int w=0, int h=0);

    /**
     * vector alias for the validate method. The values are given in array form
     * @param v array in the form [x, y, width, height]
     */
    void validate(int v[]);
};

class GuiWidget {
protected:

    GuiContainer* _parent;

    GuiRect* _rect;
    GuiProp* _prop;

    GLuint _texture;
    GLuint _bg_texture;
    GLuint _display;
    GLuint _bg_display;

    float _max_x;
    float _max_y;

    virtual void _build_display(FontManager* font);
    virtual void _build_bg_display(FontManager* font);

    int _next_p2(int p);
public:
    GuiWidget();
    GuiWidget(GuiRect* rect, GuiProp* prop, GLuint texture=0, GLuint bg_texture=0);
    virtual ~GuiWidget();

    GuiRect* rect();
    GuiProp* prop();

//    GLuint texture();
//    GLuint bg_texture();
//    GLuint display();
//    GLuint bg_display();
//
//    void set_texture(GLuint t);
//    void set_display(GLuint d);
//    void set_bg_texture(GLuint t);
//    void set_bg_display(GLuint d);

    virtual void set_parent(GuiContainer* parent);
    virtual void validate();

    virtual void input(SDL_Event* evt, unsigned int ms);
    virtual void update(unsigned int ms);
    virtual void draw(FontManager* font);

    virtual void redraw();
};

#endif	/* NRPSTG_GUIWIDGET_H */

